#ifndef xpack_ttyctrl_text_list
#define xpack_ttyctrl_text_list
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::ttyctrl_text_list::inc
#include"define/base_type.hpp"
#include"macro/xstruct.hpp"
#pragma pop_macro("xuser")

namespace mixc::ttyctrl_text_list{
    enum{ __rotate };
    using text_list_rotate_t = binaray_option<__rotate>;

    constexpr text_list_rotate_t text_list_rotate{ true };

    xstruct(
        xname(text_list),
        xprof(m_i_top, u32),
        xprof(m_i_current, u32),
        xprof(m_i_bottom, u32),
        xprof(m_is_ready, bool),
        xprof(m_count_of_visiable, u16),
        xprof(m_count, u32)
    )
    public:
        xprops()
            xpubget_priset(i_top, u32);
            xpubget_priset(i_current, u32);
            xpubget_priset(i_bottom, u32);
            xpriget_priset(is_ready, bool);

            xpubget_pubsetx(count_of_visiable, u16){
                xr{ return xthe.m_count_of_visiable; }
                xw{
                    if (xthe.m_count_of_visiable == value){
                        return;
                    }
                    xthe.m_is_ready = false;
                    xthe.m_count_of_visiable = value;
                    xthe.configure();
                }
            };

            xpubget_pubsetx(count, u32){
                xr{ return xthe.m_count; }
                xw{
                    if (xthe.m_count == u16(value)){
                        return;
                    }
                    xthe.m_is_ready = false;
                    xthe.m_count = u16(value);
                    xthe.configure();
                }
            };
        $

        xprops_operator()

    public:
        constexpr text_list():
            m_i_top{},
            m_i_current{},
            m_i_bottom{},
            m_is_ready{},
            m_count_of_visiable{},
            m_count{}{
        }

        bstate_t go(uxx i_line) const {
            if (i_line >= xthe->count){
                return bstate_t::fail;
            }
            else{
                xthe->i_current = i_line;

                // 先算 i_bottom
                xthe->i_bottom = xthe->count_of_visiable + i_line <= xthe->count ?
                    xthe->count_of_visiable + i_line - 1 :
                    xthe->count - 1;

                // 再算 i_top
                xthe->i_top = xthe->i_bottom + 1 >= xthe->count_of_visiable ?
                    xthe->i_bottom + 1 - xthe->count_of_visiable : 0;
                return bstate_t::success;
            }
        }

        text_list_rotate_t up() const {
            if (xthe->count == 0u){
                return not text_list_rotate;
            }

            if (xthe->i_current == 0u){
                xthe->i_current = xthe->count - 1;
                xthe->i_bottom = xthe->count - 1;
                xthe->i_top = xthe->count <= xthe->count_of_visiable ? 0 : xthe->count - xthe->count_of_visiable;
                return text_list_rotate;
            }

            if (xthe->i_current == xthe->i_top){
                xthe->i_current = xthe->i_current - 1;
                xthe->i_top = xthe->i_top - 1;
                xthe->i_bottom = xthe->i_bottom - 1;
                return not text_list_rotate;
            }
            else{
                xthe->i_current = xthe->i_current - 1;
                return not text_list_rotate;
            }
        }

        text_list_rotate_t down() const {
            if (xthe->count == 0u){
                return not text_list_rotate;
            }

            if (xthe->i_current + 1 == xthe->count){
                xthe->i_current = 0u;
                xthe->i_top = 0u;
                xthe->i_bottom = xthe->count <= xthe->count_of_visiable ? xthe->count - 1 : xthe->count_of_visiable - 1;
                return text_list_rotate;
            }

            if (xthe->i_current == xthe->i_bottom){
                xthe->i_current = xthe->i_current + 1;
                xthe->i_top = xthe->i_top + 1;
                xthe->i_bottom = xthe->i_bottom + 1;
                return not text_list_rotate;
            }
            else{
                xthe->i_current = xthe->i_current + 1;
                return not text_list_rotate;
            }
        }

    private:
        void configure() const {
            if (xthe->is_ready == false){
                if (xthe->is_ready = true; xthe->count == 0u or xthe->count_of_visiable == 0u){
                    xthe->i_top = 0u;
                    xthe->i_current = 0u;
                    xthe->i_bottom = 0u;
                    return;
                }

                auto diff_top_bottom = xthe->i_bottom - xthe->i_top;
                auto diff_curr_bottom = xthe->i_bottom - xthe->i_current;

                if (xthe->i_bottom >= xthe->count){
                    xthe->i_bottom = xthe->count - 1;
                    xthe->i_current = xthe->count <= diff_curr_bottom ? 0 : xthe->i_bottom - diff_curr_bottom;
                    xthe->i_top = xthe->count <= diff_top_bottom ? 0 : xthe->i_bottom - diff_top_bottom;
                }
                else if (xthe->i_bottom == 0u){
                    xthe->i_current = 0u;
                    xthe->i_top = 0u;
                    xthe->i_bottom = xthe->count <= xthe->count_of_visiable ? xthe->count - 1 : xthe->count_of_visiable - 1;
                }
                // 如果 i_bottom 不等于 0, 就保持配置
            }
        }
    $
}

namespace mixc::ttyctrl_text_list::origin{
    using mixc::ttyctrl_text_list::text_list;
    using mixc::ttyctrl_text_list::text_list_rotate;
}

#endif

xexport_space(mixc::ttyctrl_text_list::origin)
